'use strict';

const path = require('path')
const npminstall = require('npminstall')
const fse = require('fs-extra')

let pkgDir;
let pathExistsSync;

const log = require('@xqc-ink-cli/log')
const { isObject } = require('@xqc-ink-cli/utils')
const { getDefauleRegistry, getNpmLatestVersion } = require('@xqc-ink-cli/get-npm-info')
const formatPath = require('@xqc-ink-cli/format-path')
class Package {
    constructor(options){
        if(!options){
            throw new Error('Package options 不能为空')
        }
        if(!isObject(options)) {
            throw new Error('Package options 必须为对象')
        }
        // package的目标路径
        this.targetPath = options.targetPath
        // 缓存package的路径
        this.storeDir = options.storeDir
        // package的名称
        this.packageName = options.packageName
        // package的版本
        this.packageVersion = options.packageVersion
        // xqc-ink-cli/init -> xqc-ink-cli+init
        this.cachePackageName = options.packageName.replace('/', '+') 
    }
    async prepare(){
        if(!pathExistsSync) pathExistsSync = (await import('path-exists')).pathExistsSync
        if(this.storeDir && !pathExistsSync(this.storeDir)){
            // 解决目录不存在问题(Windows有待测试，macos会自动生成，并不需要fse库创建文件)
            fse.mkdirpSync(this.storeDir)
        }
        // 查出最新版本
        if(this.packageVersion === 'latest'){
            this.packageVersion = await getNpmLatestVersion(this.packageName)
        }
    }
    get cacheFilePath(){
        // storeDir: user/xxx/.xqc-ink-cli/dependencies/node_modules
        // store/xqc-cli-ink+init@1.0,4
        // /node_modules/@xqc-cli-ink/init
        return path.resolve(this.storeDir, `.store/${this.cachePackageName}@${this.packageVersion}/node_modules/${this.packageName}`)
    }
    getSpecificaCacheFilePath(packageVersion){
        return path.resolve(this.storeDir, `.store/${this.cachePackageName}@${packageVersion}`)
    }
    /**
    * Package 是否存在
    * Y:更新 Package
    * N:安装 Package
    * E: 获取本地代码入口文(获取package的入口文件)
    */
   async exists(){
        if(!pathExistsSync) pathExistsSync = (await import('path-exists')).pathExistsSync
        if(this.storeDir){
            await this.prepare()
            // console.log('cacheFilePath : ', this.cacheFilePath,  pathExistsSync(this.cacheFilePath))
            return pathExistsSync(this.cacheFilePath)
        }
        else{
            return pathExistsSync(this.targetPath) 
        }  
    }
    // N:安装 Package
    async install(){ 
        await this.prepare()
        return await npminstall({
            // install root dir
            root: this.targetPath,
            // user/xxx/.xqc-ink-cli/dependencies/node_modules
            storeDir: this.storeDir, 
            registry: getDefauleRegistry(),
            pkgs: [
              { name: this.packageName, version: this.packageVersion }
            ]
        });
    }
    // Y:更新 Package
    async update() {
        await this.prepare()
        // 1. 获取最新的版本号
        const latestVersion = await getNpmLatestVersion(this.packageName)
        // 2. 查询最新版本号的路径是否存在
        const lastesFilePath = this.getSpecificaCacheFilePath(latestVersion)
        // 3. 如果不存在，则直接安装最新版本
        if(!pathExistsSync) pathExistsSync = (await import('path-exists')).pathExistsSync
        log.verbose(`will update ${latestVersion}`)
        if(!pathExistsSync(lastesFilePath)){
            console.log('');
            log.verbose(`did update ${latestVersion}`)
            console.log(''); 
             await npminstall({
                // install root dir
                root: this.targetPath,
                // user/xxx/.xqc-ink-cli/dependencies/node_modules
                storeDir: this.storeDir, 
                registry: getDefauleRegistry(),
                pkgs: [
                  { name: this.packageName, version: latestVersion }
                ]
            });
            this.packageVersion = latestVersion
        }
        else{
            this.packageVersion = latestVersion
        } 
    }
    // E:获取本地代码入口文文件路径(获取package的入口文件路径)
    async getRootFilePath(){
        // 传入一个路径找到package.json文件
        async function _getRootFile(targetPath){
            pkgDir = await import('pkg-dir') 
            // a. 获取package.json所在目录 - pkg-dir(会向上查找)
            let dir = await pkgDir.packageDirectorySync({ cwd: targetPath });
            if(dir) {
                // b. 读取package.json - require
                const pkgFile = require(path.resolve(dir, 'package.json'))
                // c. 寻找main/lib - path
                if(pkgFile && pkgFile.main){     
                    // d. 路径兼容  
                    return formatPath(path.resolve(dir, pkgFile.main))
                }
            }
        }
        if(this.storeDir){
            return  _getRootFile(this.cacheFilePath)
        }
        else{
            return  _getRootFile(this.targetPath)
        }
        return null
    }
}
module.exports = Package;